package com.crawler.waf.filter;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.Assert;
import org.springframework.web.filter.GenericFilterBean;

import com.crawler.waf.security.authentication.PreAuthenticatedAuthenticationExtractorManager;
import com.crawler.waf.security.authentication.WafAuthenticationException;

/**
 * 自定义的Mactoken的认证处理Filter对象。其扩展自{@link GenericFilterBean}抽象类。<br>
 */
public class TokenAuthenticationProcessFilter extends GenericFilterBean {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    private AuthenticationManager authenticationManager;

    private PreAuthenticatedAuthenticationExtractorManager extractorManager;

    public TokenAuthenticationProcessFilter(
            AuthenticationManager authenticationManager, PreAuthenticatedAuthenticationExtractorManager extractorManager) {
        this.authenticationManager = authenticationManager;
        this.extractorManager = extractorManager;
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp,
                         FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        String authorization = request.getHeader("Authorization");
        if(authorization == null){
        	authorization = request.getParameter("Authorization");
        	request.removeAttribute("Authorization");
        }

        if(authorization!= null && !"".equals(authorization)) {
            long beginTime = System.currentTimeMillis();
            logger.info("TokenAuthenticationProcessFilter doFilter start beginTime:" + beginTime + ", authorization:" + authorization);

            try {
                Authentication authentication = extractorManager.extractAuthentication(authorization, request);
                Assert.notNull(authentication, "authentication");
                Authentication successAuthentication = authenticationManager.authenticate(authentication);
                SecurityContextHolder.getContext().setAuthentication(successAuthentication);
            } catch (AuthenticationException ex) {
                SecurityContextHolder.clearContext();
                throw ex;
            }  catch (Exception ex) {
            	logger.error(ex.getMessage(), ex);
   				throw new WafAuthenticationException("授权过程发生异常 " + ex.getMessage(), ex);
            } finally {
                long endTime = System.currentTimeMillis();
                logger.info("TokenAuthenticationProcessFilter doFilter end, endTime:" + endTime);
                logger.info("TokenAuthenticationProcessFilter doFilter the total time:" + (endTime - beginTime) + "ms");
            }
        }
        chain.doFilter(request, response);
    }
}
